package com.briup.es.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.briup.es.auth.SecurityUserContext;
import com.briup.es.client.BookClient;
import com.briup.es.client.ShopcarClient;
import com.briup.es.config.exception.ServiceException;
import com.briup.es.config.response.ResultCode;
import com.briup.es.constant.OrderStatus;
import com.briup.es.domain.bean.Order;
import com.briup.es.domain.bean.OrderItem;
import com.briup.es.domain.bean.Shopcar;
import com.briup.es.domain.dto.BookChangeNumDTO;
import com.briup.es.domain.dto.OrderCreateDTO;
import com.briup.es.domain.vo.OrderDetailVO;
import com.briup.es.domain.vo.OrderInfoVO;
import com.briup.es.domain.vo.OrderItemVO;
import com.briup.es.domain.vo.OrderVO;
import com.briup.es.service.OrderItemService;
import com.briup.es.service.OrderService;
import com.briup.es.mapper.OrderMapper;
import com.briup.es.util.BeanUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order>
        implements OrderService {

    private final OrderItemService orderItemService;
    private final ShopcarClient shopcarClient;
    private final BookClient bookClient;

    @Override
    public List<OrderVO> queryOrderList(Integer status) {
        // 查询当前登录用户的订单，根据状态进行条件查询
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<Order>()
                .eq(Order::getUserId, SecurityUserContext.currentUserId())
                .eq(status != null && status > 0, Order::getStatus, status);
        // 查询符合条件的订单数据
        List<Order> orders = baseMapper.selectList(wrapper);
        // 如果订单数据不为空，那么对其进行处理
        if (!CollectionUtils.isEmpty(orders)) {
            return orders.stream().map(order -> {
                OrderVO orderVO = BeanUtil.bean2VO(order, OrderVO.class);
                orderVO.setOrderId(order.getId());
                // 查询对应商品总价，及对应的商品总数
                OrderInfoVO orderInfoVO = orderItemService.queryInfoByOrderId(order.getId());
                orderVO.setTotalNum(orderInfoVO.getTotalNum());
                orderVO.setTotalPrice(orderInfoVO.getTotalPrice());
                return orderVO;
            }).toList();
        }
        return null;
    }

    @Override
    public OrderDetailVO queryOrderDetail(String orderId) {
        // 根据订单id查询订单的数据
        Order order = baseMapper.selectById(orderId);
        OrderDetailVO detailVO = BeanUtil.bean2VO(order, OrderDetailVO.class);
        // 根据订单id，查询订单项的数据
        List<OrderItemVO> orderItemVOS = orderItemService.queryByOrderId(order.getId());
        detailVO.setOrderItems(orderItemVOS);
        // 设置订单的总价和订单的总数
        // 遍历订单项数据，对订单总价和总数进行计算
        int totalNum = 0;
        double totalPrice = 0.0;
        for (OrderItemVO orderItemVO : orderItemVOS) {
            totalNum += orderItemVO.getNum();
            totalPrice += orderItemVO.getTotalPrice();
        }
        detailVO.setTotalNum(totalNum);
        detailVO.setTotalPrice(totalPrice);
        return detailVO;
    }

    @Override
    public void addOrder(OrderCreateDTO orderCreateDTO) {
        // 需要购物车项id 查询出该购物车中 对应的商品id以及对应的 商品数量
        List<Integer> shopCarIds = orderCreateDTO.getShopCarIds();
        List<Shopcar> shopcars = shopcarClient.queryByIds(shopCarIds).getData();
        if (CollectionUtils.isEmpty(shopcars) ||
                shopcars.size() != shopCarIds.size()) {
            // 如果根据购物车项id查询出的列表集合为空，那么说明该购物车项被删除了，无法生成订单
            // 或者查询出的购物车项 与 传入的购物车项id 数量不对等，也需要报错处理
            throw new ServiceException(ResultCode.SHOPCAR_ITEM_NUM_IS_ERROR);
        }

        // 调用BookService中的方法，校验图书是否下架 或 图书的库存是否足够，减少图书的库存
        List<BookChangeNumDTO> dtoList = shopcars.stream().map(shopcar -> BookChangeNumDTO.builder()
                        .bookId(shopcar.getBookId()).changeNum(-shopcar.getNum()).build())
                .toList();
        // 调用GoodsService中的方法，用于修改图书商品的库存
        bookClient.updateBookNum(dtoList);

        // 创建订单对象，添加该数据到订单表中
        Order order = initOrder(orderCreateDTO);
        baseMapper.insert(order);

        // 添加订单项的数据
        orderItemService.addOrderItems(order.getId(), shopcars);

        // 生成订单后，需要将购物项中的对应数据进行删除
        shopcarClient.deleteShopcar(shopCarIds);
    }

    @Override
    public void cancelOrder(String orderId) {
        // 关闭订单，即修改订单状态
        orderStatusTranslate(orderId, OrderStatus.NOT_PAY,
                OrderStatus.CLOSED, ResultCode.ORDER_CAN_NOT_CLOSE);

        // 如果订单可以关闭，那么关闭订单，并且将该订单对应的商品库存修复
        LambdaQueryWrapper<OrderItem> wrapper = new LambdaQueryWrapper<OrderItem>()
                .eq(OrderItem::getOrderId, orderId);
        List<OrderItem> orderItems = orderItemService.list(wrapper);
        List<BookChangeNumDTO> dtoList = orderItems.stream().map(orderItem -> BookChangeNumDTO
                .builder().bookId(orderItem.getBookId())
                .changeNum(orderItem.getNum()).build()).toList();

        // 修改图书库存数量
        bookClient.updateBookNum(dtoList);
    }

    @Override
    public void completeOrder(String orderId) {
        // 确认收货，修改订单状态
        orderStatusTranslate(orderId, OrderStatus.SENT,
                OrderStatus.RECEIVED, ResultCode.ORDER_CAN_NOT_COMPLETE);
    }

    private void orderStatusTranslate(String orderId, OrderStatus preStatus,
                                      OrderStatus newStatus, ResultCode errorCode) {
        // 确保该订单存在
        Order order = baseMapper.selectById(orderId);
        if (order == null) {
            throw new ServiceException(ResultCode.ORDER_IS_NOT_EXISTS);
        }

        // 如果订单存在，确保该订单当前状态 与待修改状态的 前置状态 一致
        if (!Objects.equals(order.getStatus(), preStatus.getCode())) {
            throw new ServiceException(errorCode);
        }

        // 修改订单状态
        LambdaUpdateWrapper<Order> wrapper = new LambdaUpdateWrapper<Order>()
                .set(Order::getStatus, newStatus.getCode())
                .eq(Order::getId, orderId);
        baseMapper.update(wrapper);
    }


    private Order initOrder(OrderCreateDTO orderCreateDTO) {
        return Order.builder()
                // 订单id通过UUID和 briup 组合生成
                .id("briup" + UUID.randomUUID().toString()
                        .replace("-", ""))
                .userId(SecurityUserContext.currentUserId())
                .status(OrderStatus.NOT_PAY.getCode())
                .createDate(LocalDateTime.now())
                .receiveUsername(orderCreateDTO.getReceiveUsername())
                .receiveAddress(orderCreateDTO.getReceiveAddress())
                .receivePhone(orderCreateDTO.getReceivePhone())
                .build();
    }
}




